
class driver_bus extends uvm_driver #(transaction_bus);
	virtual interface_bus vif;

	`uvm_component_utils(driver_bus)

	function new(string name = "drvier_bus", uvm_component parent = null);
		super.new(name, parent);
	endfunction

	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual interface_bus)::get(this, "", "vif", vif))
			`uvm_fatal("driver_bus", "virtual interface must be set for vif!!!");
	endfunction

	extern virtual task run_phase(uvm_phase phase);
	extern virtual task drive_one_pkt(transaction_bus tr);

endclass

task driver_bus::run_phase(uvm_phase phase);
	vif.bus_cmd_valid <= 1'b0;
    vif.bus_op <= 1'b0;
    vif.bus_addr <= 16'b0;
    vif.bus_wr_data <= 16'b0;
	while(!vif.rst_n)
		@(posedge vif.clk);
	while(1) begin
		seq_item_port.get_next_item(req);
        drive_one_pkt(req);
        seq_item_port.item_done();
	end
endtask

task driver_bus::drive_one_pkt(transaction_bus tr);
	// `uvm_info("driver_bus", "begin to driver one pkt ", UVM_LOW);
	repeat(1) @(posedge vif.clk);

    vif.bus_cmd_valid <= 1'b1;
    vif.bus_op <= ((tr.bus_op == BUS_RD) ? 0 : 1);
    vif.bus_addr <= tr.addr;
    vif.bus_wr_data <= ((tr.bus_op == BUS_RD) ? 0 : tr.wr_data);

    @(posedge vif.clk);
    vif.bus_cmd_valid <= 1'b0;
    vif.bus_op <= 1'b0;
    vif.bus_addr <= 16'b0;
    vif.bus_wr_data <= 16'b0;
    
    @(posedge vif.clk);
    if(tr.bus_op == BUS_RD) begin
        tr.rd_data = vif.bus_rd_data;
        `uvm_info("driver_bus", $sformatf("havs read out the register is %0h", tr.rd_data), UVM_HIGH);
    end

	// `uvm_info("driver_bus", "end driver one pkt", UVM_LOW);

endtask


